/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

package db

import (
	"hundsun.com/hsl/hschain/common/types"
)

// Option list操作选项
type Option uint

const (
	// OptionReverse 反向
	OptionReverse Option = 1 << iota
	// OptionWithKey 带key
	OptionWithKey
	// OptionWithValue 带value
	OptionWithValue
)

// IsReverse 是否反向
func IsReverse(opt Option) bool {
	return opt&OptionReverse != 0
}

// IsNeedKey 是否需要key
func IsNeedKey(opt Option) bool {
	return opt&OptionWithKey != 0
}

// IsNeedValue 是否需要value
func IsNeedValue(opt Option) bool {
	return opt&OptionWithValue != 0
}

// GenDBKey generate DB key
func GenDBKey(namespace, key []byte) []byte {
	return append(namespace, key...)
}

// List take opt list KVs
func List(it Iterator, count int32, opt Option) ([][]byte, [][]byte, error) {
	needKey := IsNeedKey(opt)
	needValue := IsNeedValue(opt)
	needReverse := IsReverse(opt)
	if count == 0 || (!needKey && !needValue) || it == nil {
		return nil, nil, types.ErrInvalidParam
	}

	var keys [][]byte
	var values [][]byte
	var i int32
	// 反向
	if needReverse {
		for it.Last(); it.Valid(); it.Prev() {
			if it.Error() != nil {
				return nil, nil, it.Error()
			}
			if needKey {
				k := cloneByte(it.Key())
				keys = append(keys, k)
			}
			if needValue {
				v := cloneByte(it.Value())
				values = append(values, v)
			}
			i++
			if count > 0 && i == count {
				break
			}
		}
		return keys, values, nil
	}
	// 正向
	for it.First(); it.Valid(); it.Next() {
		if it.Error() != nil {
			return nil, nil, it.Error()
		}
		if needKey {
			k := cloneByte(it.Key())
			keys = append(keys, k)
		}
		if needValue {
			v := cloneByte(it.Value())
			values = append(values, v)
		}
		i++
		if count > 0 && i == count {
			break
		}
	}
	return keys, values, nil
}

// ListCount 根据传入迭代器计数
func ListCount(it Iterator) int64 {
	var count int64
	for it.Next() {
		count++
	}
	return count
}

func cloneByte(v []byte) []byte {
	value := make([]byte, len(v))
	copy(value, v)
	return value
}
